package com.sinochem.yunlian.ship.base.biz;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sinochem.yunlian.ship.base.constants.BsPortConstant;
import com.sinochem.yunlian.ship.base.entity.BsMaterialCategory;
import com.sinochem.yunlian.ship.base.enume.BaseMaterialCategoryLeve;
import com.sinochem.yunlian.ship.base.mapper.BsMaterialCategoryMapper;
import com.sinochem.yunlian.ship.base.vo.request.MaterialCategoryForm;
import com.sinochem.yunlian.ship.base.vo.response.RespMaterialCategoryLeveVo;
import com.sinochem.yunlian.ship.common.biz.BaseBiz;
import com.sinochem.yunlian.ship.common.constant.DisableStatus;
import com.sinochem.yunlian.ship.common.constant.RedisKey;
import com.sinochem.yunlian.ship.common.exception.BaseException;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 货品基础信息表
 *
 * @author wh
 * @email ${email}
 * @date 2017-11-21 19:06:25
 */
@Service
public class BsMaterialCategoryBiz extends BaseBiz<BsMaterialCategoryMapper,BsMaterialCategory> {
	@Autowired
    private RedisTemplate redisTemplate;
	
	private final Logger log = LoggerFactory.getLogger(BsMaterialCategoryBiz.class);
	
	public List<BsMaterialCategory> findAllMaterialCategory() {
        return mapper.findAllMaterialCategory();
    }

	public String getBsMaterialCategoryName(Long id) {
		
		return mapper.getBsMaterialCategoryList(id);
	}

	public Page<BsMaterialCategory> findMaterialCategoryByCondition(Map params){
        Page<BsMaterialCategory> result = PageHelper.startPage(Integer.parseInt(params.get("pageNum")+""),Integer.parseInt(params.get("pageSize")+""));
        mapper.findMaterialCategoryByCondition(params);
        return result;
    }

    public List<BsMaterialCategory> findByLevel() {
        return mapper.findByLevel();
    }

    /**
     * @Description: 获取一级、二级货品列表接口
     */
	@SuppressWarnings("unchecked")
	public List<RespMaterialCategoryLeveVo> selectMaterialLevelList() {
		
		List<RespMaterialCategoryLeveVo> parents = null;
		// 获取一级、二级货品列表
        if (redisTemplate.hasKey(RedisKey.KEY_MATERIAL_CATEGORY_LEVEL_LIST)) {
            String allCategory = (String) redisTemplate.opsForValue().get(RedisKey.KEY_MATERIAL_CATEGORY_LEVEL_LIST);
            parents = JSONObject.parseArray(allCategory,RespMaterialCategoryLeveVo.class);
        } else {
			// 先获取一级货品列表
			parents = mapper.selectMaterialLevelList(BaseMaterialCategoryLeve.ONE_LEVEL.getLevel(), null);
			if (parents == null || parents.isEmpty()) {
				return null;
			}
			for (RespMaterialCategoryLeveVo categoryLeveVo : parents) {
				// 添加二级货品列表
				categoryLeveVo.setChildrens(mapper.selectMaterialLevelList(BaseMaterialCategoryLeve.TWO_LEVEL.getLevel(), categoryLeveVo.getId()));
			}
			redisTemplate.opsForValue().set(RedisKey.KEY_MATERIAL_CATEGORY_LEVEL_LIST,JSONObject.toJSONString(parents));
        }
		return parents;
	}
	/**
	 * @Description: 获取货品列表
	 */
	public HashMap<Object, Object> selectMaterialList(MaterialCategoryForm form) {
		// 根据条件货品货品列表
		PageHelper.startPage(form.getPageNum(), form.getPageSize());
		List<BsMaterialCategory> lists = mapper.selectMaterialList(form.getParentId(), form.getKeyWord());
		PageInfo<BsMaterialCategory> page = new PageInfo<>(lists);
		HashMap<Object,Object> hashMap = new HashMap<>();
		hashMap.put("total", page.getTotal());
		hashMap.put("materialList", lists);
		
		return hashMap;
	}
	/**
	 * 
	 * @param maxLevel 
	 * @param dealing 
	 * @Description: 更新货品状态
	 */
	@Transactional(rollbackFor =  Exception.class)
	public void updateMaterialDisableStatus(Long id, Integer disableStatus, BsMaterialCategory materialCategory, int maxLevel, HasDealing dealing) throws SQLException{
		
		if (maxLevel == materialCategory.getLevel()) {
			
			updateMaterialRootStatus(materialCategory, disableStatus, dealing);
			// 叶子节点
			mapper.updateMaterialDisableStatus(id, disableStatus, null);
		} else {
			// 存在子节点,获取所有叶子节点
			List<BsMaterialCategory> lists = mapper.selectMaterialCategoryList(materialCategory.getId());
			// 更新父节点状态
			updateMaterialRootStatus(materialCategory, disableStatus, dealing);
			if (lists == null || lists.isEmpty()) {
				mapper.updateMaterialDisableStatus(id, disableStatus, null);
				return;
			}
			mapper.updateMaterialDisableStatus(id, disableStatus, null);
			
			for (BsMaterialCategory material : lists ){
				updateMaterialDisableStatus(material.getId(), disableStatus, material, maxLevel, dealing);
			}
		}
	}
	
	public void updateMaterialCategory(Long id, Integer disableStatus, BsMaterialCategory materialCategory, int maxLevel) {
		HasDealing dealing = new HasDealing();
		try {
			updateMaterialDisableStatus(id, disableStatus, materialCategory, maxLevel, dealing);
		}  catch (SQLException e) {
			log.error("操作失败了{}",e);
			throw BaseException.message("操作失败了");
		}
		
	}
	
	
	/**
	 * 
	 * @param dealing 
	 * @Description: 启用子节点时检查父节点状态
	 */
	public void updateMaterialRootStatus(BsMaterialCategory materialCategory, Integer disableStatus, HasDealing dealing) {
		
		if (materialCategory.getParentId() != 0 && DisableStatus.STATUS_ENABLE == disableStatus && !dealing.hasDealing) {
			// 不是根节点
			log.info("存在父节点，父节点的id为:{}", materialCategory.getParentId());
			mapper.updateMaterialDisableStatus(materialCategory.getParentId(), disableStatus, null);
			BsMaterialCategory parentMaterial = this.selectMaterialById(materialCategory.getParentId());
			if (parentMaterial != null) {
				updateMaterialRootStatus(parentMaterial, disableStatus, dealing);
			} else {
				dealing.hasDealing = true;
			}
			
		} else {
			dealing.hasDealing = true;
		}
	}
	/**
	 * 
	 * @Description: 根据id获取货品
	 */
	public BsMaterialCategory selectMaterialById(Long id) {
		
		return mapper.selectMaterialById(id);
	}
	/**
	 * 
	 * @Description: 根据id获取货品详情
	 */
	public HashMap<Object, Object> selectMaterialDetail(Long id) {
		
		HashMap<Object,Object> hashMap = new HashMap<>();
		// 获取当前的货品信息
		BsMaterialCategory materialCategory = this.selectMaterialById(id);
		if (materialCategory == null) {
			return null;
		}
		hashMap.put("id", materialCategory.getId());
		hashMap.put("categoryName", materialCategory.getCategoryName());
		hashMap.put("seqNum", materialCategory.getSeqNum());
		if (materialCategory.getLevel() == BaseMaterialCategoryLeve.ONE_LEVEL.getLevel()) {
			
			hashMap.put("parentLevel", 0);
			hashMap.put("parentId", 0);
			hashMap.put("parentCategoryName", "根目录");
			// 设置根目录
			ArrayList<RespMaterialCategoryLeveVo> lists = new ArrayList<>();
			RespMaterialCategoryLeveVo categoryLeveVo = new RespMaterialCategoryLeveVo();
			// 根目录赋值
			categoryLeveVo.setCategoryName("根目录");
			categoryLeveVo.setId(0L);
			
			lists.add(categoryLeveVo);
			hashMap.put("materialLevel", lists);
		}
		// 获取父类货品信息
		BsMaterialCategory parentMaterialCategory = this.selectMaterialById(materialCategory.getParentId());
		if (parentMaterialCategory == null) {
			log.info("无父类信息:{}", parentMaterialCategory);
			return hashMap;
		}
		hashMap.put("parentLevel", parentMaterialCategory.getLevel());
		hashMap.put("parentId", parentMaterialCategory.getId());
		hashMap.put("parentCategoryName", parentMaterialCategory.getCategoryName());
		// 获取父节点的所有货品信息
		List<RespMaterialCategoryLeveVo> parents = mapper.selectMaterialLevelList(parentMaterialCategory.getLevel(), null);
		
		hashMap.put("materialLevel", parents);
		return hashMap;
	}
	/**
	 * 注：多服务情况下可能会存在数据不一致性 (待添加分布式锁)
	 * @Description: 修改/添加货品接口
	 */
	public void updateMaterial(Long parentId, String categoryName, Long id, Integer seqNum) {
		
		if (id == null && parentId != null) {
			// 添加操作
			
			if (StringUtils.isEmpty(categoryName)) {
				throw BaseException.message("货品名称不能为空");
			}
			BsMaterialCategory material =  new BsMaterialCategory();
			// 获取当前最大的排序号
			int maxSeqNum = mapper.selectMaterialMaxSeqNum();
			
			if (parentId == 0) {
				// 添加根目录下的一级节点
				// 检查货品名称是否存在
				insertRootNode(categoryName, material, maxSeqNum);
				return;
			}
			// insert非根节点
			insertNoRootNode(categoryName, parentId, material, maxSeqNum);
			
		} else {
			
			// 更新操作
			upateMaterialCategory(parentId, categoryName, id, seqNum);
			
		}
		
	}
	/**
	 * 
	 * @Description:更新操作货品
	 */
	private void upateMaterialCategory(Long parentId, String categoryName, Long id, Integer seqNum) {
		
		if (StringUtils.isEmpty(categoryName) || seqNum == null || parentId == null) {
			throw BaseException.message("更新数据不能为空");
		}
		BsMaterialCategory parentMaterialCategory = null;
		if (parentId != 0) {
			// 非根节点
			// 判断父节点是否存在
			parentMaterialCategory = this.selectMaterialById(parentId);
			if (parentMaterialCategory == null) {
				throw BaseException.message("您选择的父节点不存在");
			}
		}
		// 判断要更新的节点是否存在
		BsMaterialCategory materialCategory = this.selectMaterialById(id);
		if (materialCategory == null) {
			throw BaseException.message("不存在您要更改的货品");
		}
		// 非根节点
		if (parentId != 0 && (parentMaterialCategory.getLevel() + 1) != materialCategory.getLevel()) {
			throw BaseException.message("您应该选择第" + BaseMaterialCategoryLeve.returnMessage(materialCategory.getLevel() - 1));
		}
		// 根节点
		if (parentId == 0 &&  BaseMaterialCategoryLeve.ONE_LEVEL.getLevel() != materialCategory.getLevel()) {
			throw BaseException.message("您应该选择根节点");
		}
		if (!categoryName.equals(materialCategory.getCategoryName())) {
			// 检查货品名称是否存在
			BsMaterialCategory category = mapper.selectMaterialByCategoryNameAndLevel(categoryName, materialCategory.getLevel());
			if (category != null) {
				throw BaseException.message("货品名称:" + categoryName + "已存在");
			}
		}
		materialCategory.setCategoryName(categoryName);
		materialCategory.setSeqNum(seqNum);
		if (parentId == 0) {
			// 根节点
			materialCategory.setParentId(0L);
		} else {
			// 非根节点
			materialCategory.setParentId(parentMaterialCategory.getId());
		}

		mapper.updateByPrimaryKeySelective(materialCategory);
		// 清除缓存
		redisTemplate.delete(RedisKey.KEY_MATERIAL_CATEGORY_LEVEL_LIST);
	}
	/**
	 * 
	 * @Description: insert非根节点
	 */
	private void insertNoRootNode(String categoryName, Long parentId, BsMaterialCategory material, int maxSeqNum) {
		
		// 判断要添加的货品是否存在
		BsMaterialCategory materialCategory = this.selectMaterialById(parentId);
		if (materialCategory == null) {
			throw BaseException.message("不存在您选择的货品等级");
		}
		if (materialCategory.getLevel() > 2) {
			throw BaseException.message("您选择的货品等级超出范围");
		}
		// 检查货品名称是否存在
		BsMaterialCategory category = mapper.selectMaterialByCategoryNameAndLevel(categoryName, materialCategory.getLevel() + 1);
		if (category != null) {
			throw BaseException.message("货品名称:" + categoryName + "已存在");
		}
		// 获取当前节点最大编码 
		String maxEnName = mapper.selectMaterialMaxEnName(materialCategory.getId());
		boolean isOneLine = false;
		if (maxEnName == null) {
			maxEnName = mapper.selectMaterialMaxEnNameById(materialCategory.getId());
			isOneLine = true;
		}
		// 添加货品
		material.setCategoryName(categoryName);
		material.setDisableStatus(DisableStatus.STATUS_ENABLE);
		material.setGroupId(0);
		material.setEnName(getEnName(maxEnName, 1, isOneLine, materialCategory.getLevel() + 1));
		material.setLevel(materialCategory.getLevel() + 1);
		material.setParentId(materialCategory.getId());
		material.setSeqNum(maxSeqNum  + 2);
		material.setDeleteStatus(BsPortConstant.STATUS_ENABLE);
		mapper.insertSelective(material);
		redisTemplate.delete(RedisKey.KEY_MATERIAL_CATEGORY_LEVEL_LIST);
	}
	/**
	 * 
	 * @Description: insert根节点
	 */
	private void insertRootNode(String categoryName, BsMaterialCategory material, int maxSeqNum) {
		
		BsMaterialCategory category = mapper.selectMaterialByCategoryNameAndLevel(categoryName, BaseMaterialCategoryLeve.ONE_LEVEL.getLevel());
		if (category != null) {
			throw BaseException.message("货品名称:" + categoryName + "已存在");
		}
		// 获取当前节点最大编码 
		String maxEnName = mapper.selectMaterialMaxEnName(0L);
		// 添加一级节点
		material.setCategoryName(categoryName);
		material.setDisableStatus(DisableStatus.STATUS_ENABLE);
		material.setGroupId(0);
		material.setEnName(getEnName(maxEnName, 1, false, null));
		material.setLevel(BaseMaterialCategoryLeve.ONE_LEVEL.getLevel());
		material.setParentId(0L);
		// 单数增长
		material.setSeqNum(maxSeqNum  + 2); 
		material.setDeleteStatus(BsPortConstant.STATUS_ENABLE);
		mapper.insertSelective(material);
		redisTemplate.delete(RedisKey.KEY_MATERIAL_CATEGORY_LEVEL_LIST);
	}
	
	public static String getEnName(String enName, Integer increase, boolean isOneLine, Integer level) {
		if (StringUtils.isEmpty(enName)) {
			return null;
		}
		if (isOneLine && level != null && BaseMaterialCategoryLeve.THREE_LEVEL.getLevel() == level) {
			// 三类货品
			return enName + "00";
		} else if (isOneLine) {
			// 一、二类货品
			return enName + "01";
		}
		// 编码长度
		int strLen = enName.length();
		// 转为Integer类型
		Integer value = Integer.parseInt(enName);
		// 前缀是否存在0
		int residuLen = strLen - ((Integer)Integer.parseInt(enName)).toString().length();
		// 当前值加上某个值，得到最新值
		Integer newValue = value + increase;
		StringBuffer sBuffer =  new StringBuffer();
		if (residuLen > 0 && strLen > newValue.toString().length()) {
			// 存在前缀0
			for (int i = 0 ; i < residuLen; i++) {
				sBuffer.append(0);
			}
		} 
		sBuffer.append(newValue);
		return sBuffer.toString();
	}

    public List<BsMaterialCategory> findMaterialCategoryListByMap(Map params) {
        return mapper.findMaterialCategoryListByMap(params);
    }

	public int selectMaterialMaxLevel() {
		// TODO Auto-generated method stub
		return mapper.selectMaterialMaxLevel();
	}

	/**
	 * 
	 */
	@Data
	class HasDealing {
		
		public  Boolean hasDealing = false;
	}
	
	
}